//
//  ZYStoryTransitiomScrollView.m
//  allTest
//
//  Created by 李培根 on 2018/11/8.
//  Copyright © 2018 李培根. All rights reserved.
//

#import "ZYStoryTransitiomScrollView.h"
#import <YYCategories.h>

@interface ZYStoryTransitiomScrollView ()<UIScrollViewDelegate>

@property (nonatomic, assign) BOOL beginDrag; //是否开始拖拽
@property (nonatomic, assign) CGFloat scrollOffX; //记录最开始拖拽的offsetX
@property (nonatomic, assign) BOOL duringDragging;// 该字段意思是，自开始拖拽到拖拽结束，中间如果有放松又l拖拽，只算前一次拖拽
@property (nonatomic, assign) NSInteger lastIndex;
@property (nonatomic, assign) CGFloat lastLeft; //记录上一次的scrollView的偏移量
@property (nonatomic, assign, readonly) CGFloat viewWidth;

@end


@implementation ZYStoryTransitiomScrollView

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.duringDragging = NO; //初始化为 不在拖拽中
        self.pagingEnabled = YES;
        self.delegate = self;
    }
    return self;
}

- (void)setViewArray:(NSArray<__kindof UIView *> *)viewArray {
    _viewArray = viewArray;
    [self removeAllSubviews];
    for (NSInteger i = 0; i < viewArray.count; i++) {
        UIView *view = viewArray[i];
        view.frame = CGRectMake(self.viewWidth * i, 0, self.viewWidth, self.frame.size.height);
        [self addSubview:view];
    }
    self.contentSize = CGSizeMake(self.viewWidth * viewArray.count, self.frame.size.height);
}

- (void)setSelectedIndex:(NSInteger)selectedIndex {
    _selectedIndex = selectedIndex;
    self.contentOffset = CGPointMake(self.viewWidth * selectedIndex, 0);
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    printf("%s\n", __FUNCTION__);
    //    NSLog(@"contentOffset = %@", @(scrollView.contentOffset));
    
    CGFloat left = scrollView.contentOffset.x - self.scrollOffX; //获取相对开始拖拽的偏移差值
    CGFloat decimal = left - (NSInteger)left; //取小数部分
    left = (NSInteger)left % ((NSInteger)scrollView.frame.size.width); //对view的宽度取余
    left += decimal; //加上小数部分
    //添加以上代码，是因为后续的代码中，ratio的取值都在其绝对值的0到1之间，所以以此来保证ratio的取值范围
    //以上问题的复现方法就是  用户在第0页向左拖拽，然后松手，快完全显示第1页时，用户马上再次拖拽
    //由于松开再拖拽，为了解决其他的问题，在本逻辑中算一次拖拽，所以scrollOffX还是第0页的值，从而导致了left的绝对值会超过scrollView的宽度
    NSLog(@"left = %@, contentOffsetX = %@, self.scrollOffX = %@", @(left), @(scrollView.contentOffset.x), @(self.scrollOffX));
    
    CGFloat ratio = left / scrollView.frame.size.width;
    
    //由于在用户松手之后，page会变更，从而导致view会错乱，因为更之前的view不一样
    //添加一下判断来避免该问题
    if (fabs(ratio) == 1) {
        return;
    }
    
    CGFloat indexValue = scrollView.contentOffset.x / kScreenWidth;
    NSInteger index = (NSInteger)(left < 0 ? ceilf(indexValue) : floorf(indexValue));
    
    //在连续拖拽过程中，发现问题，超过了一个单位宽度，中间view的旋转轴没有及时更新，所以添加以下代码
    if (index != self.lastIndex) {
        self.beginDrag = YES;
        self.lastIndex = index;
    } else {
        //又发现问题，用户在同一个界面左右切换，还是会导致当前view的旋转轴没有及时更新
        //而同一个界面，左右滑动，会导致偏移量相对于初始位置的数值异号，所以需要记录上次的left，标记为全局变量lastLeft
        if (self.lastLeft * left < 0) {
            self.beginDrag = YES;
        }
        self.lastLeft = left;
    }
    
    
    if (index >= 0 && index < self.viewArray.count) {
        UIView *preView = nil;
        UIView *curView = self.viewArray[index];
        UIView *nextView = nil;
        if (index - 1 >= 0) {
            preView = self.viewArray[index - 1];
        }
        if (index + 1 < self.viewArray.count) {
            nextView = self.viewArray[index + 1];
        }
        if (left > 0) {
            if (self.beginDrag) {
                //在开始拖拽的时候
                [self restoreView:curView index:index];
                [self restoreView:preView index:index-1];
                [self restoreView:nextView index:index+1];
                curView.layer.anchorPoint = CGPointMake(1, 0.5);
                curView.left = kScreenWidth * index;
                nextView.layer.anchorPoint = CGPointMake(0, 0.5);
                nextView.left = kScreenWidth * (index + 1);
            }
            // 向左 ratio 0 -> 1
            //当前view绕右边 0 -> -M_PI_2
            curView.layer.transform = [self transformWithRatio:-ratio];
            
            //下个view绕左边 M_PI_2 -> 0
            nextView.layer.transform = [self transformWithRatio:1-ratio];
            //前个view不变
        } else {
            if (self.beginDrag) {
                [self restoreView:curView index:index];
                [self restoreView:preView index:index-1];
                [self restoreView:nextView index:index+1];
                curView.layer.anchorPoint = CGPointMake(0, 0.5);
                curView.left = kScreenWidth * index;
                preView.layer.anchorPoint = CGPointMake(1, 0.5);
                preView.left = kScreenWidth * (index - 1);
            }
            // 向右 ratio 0 -> -1
            //当前view绕左边 0 -> M_PI_2
            curView.layer.transform = [self transformWithRatio:-ratio];
            
            //前个view绕右边 -M_PI_2 -> 0
            preView.layer.transform = [self transformWithRatio:-(1 + ratio)];
            //下个view不变
        }
    }
    self.beginDrag = NO;
    NSLog(@"direction = %@, current page = %@ ratio = %@", (left < 0 ? @"right" : @"left"), @(index), @(ratio));
}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
    if (!self.duringDragging) {
        self.lastIndex = scrollView.contentOffset.x / scrollView.width;
        self.scrollOffX = scrollView.contentOffset.x;
        self.lastLeft = 0;
        self.beginDrag = YES;
        self.duringDragging = YES;
    }
    //    printf("%s\n", __FUNCTION__);
    //    NSLog(@"contentOffset = %@", @(scrollView.contentOffset));
}


- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    CGFloat offSetX = scrollView.contentOffset.x;
    NSInteger offSetXInt = (NSInteger)offSetX;
    if (offSetX - offSetXInt <= 0.000001) {
        //下面的判断有问题，因为offSetXInt强行取整，会导致部分边界问题，所以添加上面判断
        if (offSetXInt % (NSInteger)scrollView.frame.size.width == 0) {
            self.duringDragging = NO;
            printf("%s\n", __FUNCTION__);
            for (NSInteger i = 0; i < self.viewArray.count; i++) {
                UIView *view = self.viewArray[i];
                view.layer.transform = CATransform3DIdentity;
                view.frame = CGRectMake(kScreenWidth * i, 0, kScreenWidth, kScreenHeight);
            }
        }
    }
}

- (void)restoreView:(UIView *)view index:(NSInteger)index {
    view.layer.transform = CATransform3DIdentity;
    view.frame = CGRectMake(kScreenWidth * index, 0, kScreenWidth, kScreenHeight);
}

- (CATransform3D)transformWithRatio:(CGFloat)ratio {
    //    NSLog(@"real ratio = %@", @(ratio));
    CATransform3D transform = CATransform3DIdentity;
    transform.m34 = -1.0f / 1500;
    transform = CATransform3DRotate(transform, M_PI_2 * 1 * ratio, 0, 1, 0);
    return transform;
}

- (CGFloat)viewWidth {
    return CGRectGetWidth(self.frame);
}

@end
